package com.study.bindview_compiler;

import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;

import java.util.ArrayList;
import java.util.List;

import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;

/**
 * 作者： zjf 10/15/20 4:47 PM
 * 描述：
 */
public class AnnotatedClass {

    public static final ClassName INJECTOR = ClassName.get("com.study.bindview", "Injector");
    final ClassName FINDER = ClassName.get("com.study.bindview", "Finder");
    final ClassName VIEW = ClassName.get("android.view", "View");
    public static final ClassName ONCLICK_LISTENER = ClassName.get("android.view", "View", "OnClickListener");


    TypeElement typeElement;
    Elements mElementUtils;
    List<BindViewField> bindViewFields;
    List<OnClickMethod> onClickMethods;

    public AnnotatedClass(TypeElement typeElement, Elements mElementUtils) {
        this.typeElement = typeElement;
        this.mElementUtils = mElementUtils;
        bindViewFields = new ArrayList<>();
        onClickMethods = new ArrayList<>();
    }

    public JavaFile getCode() {
        MethodSpec.Builder methodBuilder = MethodSpec
                .methodBuilder("inject")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Override.class)
                .addParameter(TypeName.get(typeElement.asType()), "target", Modifier.FINAL)
                .addParameter(TypeName.OBJECT, "source")
                .addParameter(FINDER, "finder");
        for (BindViewField field : bindViewFields) {
            methodBuilder.addStatement("target.$N = ($T)finder.findView(source, $L)",
                    field.getFieldName(), ClassName.get(field.getFieldType()), field.getResId());
        }

        if (onClickMethods.size() > 0) {
            for (OnClickMethod method : onClickMethods) {
                MethodSpec build = MethodSpec
                        .methodBuilder("onClick")
                        .addAnnotation(Override.class)
                        .addModifiers(Modifier.PUBLIC)
                        .returns(TypeName.VOID)
                        .addParameter(VIEW, "view")
                        .addStatement("target.$N(view)", method.getMethodName())
                        .build();
                TypeSpec listener = TypeSpec
                        .anonymousClassBuilder("")
                        .addSuperinterface(ONCLICK_LISTENER)
                        .addMethod(build)
                        .build();

                methodBuilder.addStatement("$T listener = $L", ONCLICK_LISTENER, listener);

                for (int id : method.getIds()) {
                    methodBuilder.addStatement("finder.findView(source,$L).setOnClickListener(listener)", id);
                }
            }
        }

        String packageName = mElementUtils.getPackageOf(typeElement).toString();
        String className = typeElement.getQualifiedName().toString().substring(packageName.length() + 1) + "_Injector";

        TypeSpec typeSpec = TypeSpec
                .classBuilder(className)
                .addModifiers(Modifier.PUBLIC)
                .addSuperinterface(ParameterizedTypeName.get(INJECTOR, TypeName.get(typeElement.asType())))
                .addMethod(methodBuilder.build())
                .build();

        return JavaFile.builder(packageName, typeSpec).build();
    }

    public void addField(BindViewField field) {
        bindViewFields.add(field);
    }

    public void addMethod(OnClickMethod method) {
        onClickMethods.add(method);
    }
}
